import {defineStore} from "pinia";
import {TreeOptionData} from 'tdesign-vue-next';
import {contains, group, map, MapWrap} from "@/utils/lang/ArrayUtil";
import LocalNameEnum from "@/enumeration/LocalNameEnum";
import {getFromOneByAsync, listRecordByAsync, removeOneByAsync, saveOneByAsync} from "@/utils/utools/DbStorageUtil";
import {PluginSettingContent, PluginSettingIndex, PluginSettingTypeEnum} from "@/entity/setting/PluginSetting";
import {useThemeSettingStore} from "@/store/setting/ThemeSettingStore";
import {FileIcon, FolderIcon} from 'tdesign-icons-vue-next';

export const PLUGIN_FOLDER_KEYS = ['theme', 'markdown-menu', 'markdown-syntax'];

export interface PluginItem {
  id: number;
  name: string;
  content: string;
}

export const pluginTypes = [{
  key: PluginSettingTypeEnum.ALL,
  title: '全部'
}, {
  key: PluginSettingTypeEnum.THEME,
  title: '主题'
}, {
  key: PluginSettingTypeEnum.MARKDOWN_MENU,
  title: 'markdown菜单'
}, {
  key: PluginSettingTypeEnum.MARKDOWN_SYNTAX,
  title: 'markdown语法'
}, {
  key: PluginSettingTypeEnum.RICH_TEXT_PLUGIN,
  title: '富文本语法'
}, {
  key: PluginSettingTypeEnum.MARKDOWN_TEMPLATE,
  title: 'markdown模板'
}];

export const usePluginSettingStore = defineStore(LocalNameEnum.SETTING_PLUGIN, () => {
  const items = ref(new Array<PluginSettingIndex>())
  let rev: string | undefined = undefined;

  const pluginTree = computed<Array<TreeOptionData>>(() => {
    const itemMap = group(items.value, 'type');
    return [{
      value: 'theme',
      label: '主题',
      leaf: false,
      icon: () => h(FolderIcon),
      children: itemMap.getOrDefault(PluginSettingTypeEnum.THEME, []).map(item => ({
        value: item.id,
        label: item.name,
        leaf: true,
        icon: () => h(FileIcon)
      }))
    }, {
      value: 'markdown-menu',
      label: 'markdown菜单',
      leaf: false,
      icon: () => h(FolderIcon),
      children: itemMap.getOrDefault(PluginSettingTypeEnum.MARKDOWN_MENU, []).map(item => ({
        value: item.id,
        label: item.name,
        leaf: true,
        icon: () => h(FileIcon)
      }))
    }, {
      value: 'markdown-syntax',
      label: 'markdown语法',
      leaf: false,
      icon: () => h(FolderIcon),
      children: itemMap.getOrDefault(PluginSettingTypeEnum.MARKDOWN_SYNTAX, []).map(item => ({
        value: item.id,
        label: item.name,
        leaf: true,
        icon: () => h(FileIcon)
      }))
    }, {
      value: 'markdown-template',
      label: 'markdown模板',
      leaf: false,
      icon: () => h(FolderIcon),
      children: itemMap.getOrDefault(PluginSettingTypeEnum.MARKDOWN_TEMPLATE, []).map(item => ({
        value: item.id,
        label: item.name,
        leaf: true,
        icon: () => h(FileIcon)
      }))
    }];
  })
  const pluginMap = computed<MapWrap<number, PluginSettingIndex>>(() => map(items.value, 'id'))

  const installIds = computed(() => items.value.filter(e => e.originId)
    .map(e => e.originId || 0));
  const installApplicationIds = computed(() => items.value
    .filter(e => e.originApplicationId)
    .map(e => e.originApplicationId || 0));

  const markdownTemplates = computed(() =>
    items.value.filter(item => item.type === PluginSettingTypeEnum.MARKDOWN_TEMPLATE));

  async function init() {
    const res = await getFromOneByAsync<Array<PluginSettingIndex>>(LocalNameEnum.SETTING_PLUGIN);
    if (res.record) {
      items.value = res.record;
    }
    rev = res.rev;
  }

  async function save() {
    rev = await saveOneByAsync(LocalNameEnum.SETTING_PLUGIN, items.value, rev);
  }

  async function add(item: Omit<PluginSettingIndex, 'id'>, content = '') {
    const id = new Date().getTime();
    items.value.push({
      ...item,
      id,
    });
    await save();
    await saveOneByAsync<PluginSettingContent>(`${LocalNameEnum.LIST_PLUGIN_CONTENT}/${id}`, {
      id,
      content
    });
  }

  function rename(id: number, name: string) {
    const index = items.value.findIndex(item => item.id === id);
    if (index === -1) {
      // 不存在，新增一个
      return Promise.reject(new Error("插件不存在"));
    }
    items.value[index] = {
      ...items.value[index],
      name
    }
    return save();
  }

  function update(id: number, data: Partial<PluginSettingIndex>) {
    const index = items.value.findIndex(item => item.id === id);
    if (index === -1) {
      // 不存在，新增一个
      return Promise.reject(new Error("插件不存在"));
    }
    items.value[index] = {
      ...items.value[index],
      ...data
    }
    return save();
  }

  function saveContent(id: number, content: PluginSettingContent, contentRev: string | undefined) {
    if (items.value.findIndex(item => item.id === id) === -1) {
      // 不存在，新增一个
      return Promise.reject(new Error("插件不存在"));
    }
    return saveOneByAsync(`${LocalNameEnum.LIST_PLUGIN_CONTENT}/${id}`, {
      ...content,
      id
    }, contentRev);
  }

  async function remove(id: number) {
    const index = items.value.findIndex(item => item.id === id);
    if (index === -1) {
      return Promise.reject(new Error("插件不存在"));
    }
    items.value.splice(index, 1);
    await save();
    // 删除内容
    await removeOneByAsync(`${LocalNameEnum.LIST_PLUGIN_CONTENT}/${id}`, true)
  }

  async function removeApplicationId(applicationId: number) {
    const index = items.value.findIndex(item => item.originApplicationId === applicationId);
    if (index === -1) {
      return Promise.reject(new Error("插件不存在"));
    }
    let source = items.value[index];
    items.value.splice(index, 1);
    await save();
    // 删除内容
    await removeOneByAsync(`${LocalNameEnum.LIST_PLUGIN_CONTENT}/${source.id}`, true)
  }

  function getContent(id: number) {
    return getFromOneByAsync<PluginSettingContent>(`${LocalNameEnum.LIST_PLUGIN_CONTENT}/${id}`);
  }

  async function getPlugins(type: PluginSettingTypeEnum): Promise<Array<PluginItem>> {
    let indexes = items.value.filter(item => item.type === type);

    if (indexes.length === 0) {
      return Promise.resolve([])
    }

    // 过滤掉没启用的

    switch (type) {
      case PluginSettingTypeEnum.MARKDOWN_MENU:
        const {markdownMenus} = useThemeSettingStore();
        indexes = indexes.filter(item => contains(markdownMenus, item.id));
        break;
      case PluginSettingTypeEnum.MARKDOWN_SYNTAX:
        const {markdownSyntaxes} = useThemeSettingStore();
        indexes = indexes.filter(item => contains(markdownSyntaxes, item.id));
        break;
    }


    const records = await listRecordByAsync<PluginSettingContent>(indexes.map(item => `${LocalNameEnum.LIST_PLUGIN_CONTENT}/${item.id}`));

    const recordMap = map(records.map(record => record.record), 'id');

    return indexes.map(item => {
      const record = recordMap.getOrDefault(item.id, {id: item.id, content: ''});
      return {
        id: item.id,
        name: item.name,
        content: record.content
      }
    }).filter(item => item.content !== '');

  }

  async function getThemeContent(id: number): Promise<string> {
    const index = items.value.findIndex(item => item.id === id);

    if (index === -1) {
      return Promise.resolve('')
    }

    if (items.value[index].type !== PluginSettingTypeEnum.THEME) {
      return Promise.resolve('')
    }

    const record = await getFromOneByAsync<PluginSettingContent>(`${LocalNameEnum.LIST_PLUGIN_CONTENT}/${id}`);

    return record.record ? record.record.content : '';

  }

  return {
    plugins: items, pluginTree, pluginMap, markdownTemplates,
    installIds, installApplicationIds,
    init, save, add, update, rename, saveContent, remove, getContent,
    getPlugins, getThemeContent, removeApplicationId
  }

})
